package com.heima.common.es;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

/**
 * @author itheima
 * @since 2022-07-18
 */
@Component
public class ElasticSearchTemplate {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 执行查询
     *
     * @param indexName   索引名
     * @param query       查询构造器
     * @param skip        页码
     * @param size        每页显示条数
     * @param orderBy     排序字段
     * @param orderByType 排序方式
     * @return SearchResponse
     * @throws IOException IOException
     */
    public SearchResponse search(String indexName, AbstractQueryBuilder query, HighlightBuilder highlightBuilder, Integer skip, Integer size, String orderBy, SortOrder orderByType) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 分页
        searchSourceBuilder.from(skip);
        searchSourceBuilder.size(size);

        // 排序
        searchSourceBuilder.sort(orderBy, orderByType);

        // 查询条件
        searchSourceBuilder.query(query);

        // 高亮
        if (highlightBuilder != null) {
            searchSourceBuilder.highlighter(highlightBuilder);
        }

        searchRequest.source(searchSourceBuilder);

        return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    }

    /**
     * 构建布尔查询
     *
     * @param map 查询条件
     * @return BoolQueryBuilder
     * @throws IOException IOException
     */
    public BoolQueryBuilder getBoolQueryBuilder(Map<String, AbstractQueryBuilder> map) throws IOException {
        //布尔查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Set<String> keySet = map.keySet();

        for (String key : keySet) {
            if (StringUtils.isEmpty(key)) {
                continue;
            }

            AbstractQueryBuilder abstractQueryBuilder = map.get(key);
            if ("must".equals(key)) {
                boolQueryBuilder.must(abstractQueryBuilder);
            } else if ("filter".equals(key)) {
                boolQueryBuilder.filter(abstractQueryBuilder);
            }
        }

        return boolQueryBuilder;
    }


    /**
     * 构建高亮查询
     *
     * @param title 高亮内容
     * @param pre   高亮前缀
     * @param post  高亮后缀
     * @return HighlightBuilder
     */
    public HighlightBuilder getHighlightBuilder(String title, String pre, String post) {
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field(title);
        highlightBuilder.preTags(pre);
        highlightBuilder.postTags(post);
        return highlightBuilder;
    }

    /**
     * 构建字符串查询
     *
     * @param keyword  关键词
     * @param operator 连接条件
     * @param fields   查询字段（多个）
     * @return QueryStringQueryBuilder
     */
    public QueryStringQueryBuilder getStringQueryBuilder(String keyword, Operator operator, String... fields) {
        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(keyword);
        if (ArrayUtils.isEmpty(fields)) {
            return queryStringQueryBuilder;
        }

        for (String field : fields) {
            if (StringUtils.isEmpty(field)) {
                continue;
            }

            queryStringQueryBuilder = queryStringQueryBuilder.field(field);
        }

        return queryStringQueryBuilder.defaultOperator(operator);
    }

    /**
     * 范围查询
     *
     * @param field     查询字段
     * @param condition 查询条件(key="lt小于, gt大于, let小于等于, gte大于等于")
     * @return RangeQueryBuilder
     */
    public RangeQueryBuilder getRangeBuilder(String field, Map<String, Object> condition) {
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(field);
        Set<String> keySet = condition.keySet();
        if (CollectionUtils.isEmpty(keySet)) {
            return rangeQueryBuilder;
        }

        for (String key : keySet) {
            if (StringUtils.isEmpty(key)) {
                continue;
            }

            Object value = condition.get(key);

            if ("lt".equals(key)) {
                rangeQueryBuilder = rangeQueryBuilder.lt(value);
            } else if ("gt".equals(key)) {
                rangeQueryBuilder = rangeQueryBuilder.gt(value);
            } else if ("lte".equals(key)) {
                rangeQueryBuilder = rangeQueryBuilder.lte(value);
            } else if ("gte".equals(key)) {
                rangeQueryBuilder = rangeQueryBuilder.gte(value);
            }
        }

        return rangeQueryBuilder;
    }

}
